﻿using Shinva.LADModel.Models;
using Shinva.Variables.Interface;
using Shinva.Variables.Models;
using Shinva.Variables.Type.bit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Shinva.LADModel.Abstractions
{
    /// <summary>
    /// 这是虚拟节点，虚拟节点中与图元节点不同，输入实例有多个，输出实例只有一个
    /// </summary>
    public class VirtualNode : IGraphNode
    {
        public string Name = "VN";
        public int Id { get; set; } 
        public NodeType NodeType { get; set; } = NodeType.VirtualNode;


        /// <summary>
        /// 此结构保存当前图元的所有属性：input、output、inout还有自定义的en\eno\in1\in2\in3等等
        /// </summary>
        public Dictionary<string, PlcBool> Attributes { get; set; } = new Dictionary<string, PlcBool>();



        /// <summary>
        /// 这是变量表接口,存储变量名和变量实例的地方
        /// </summary>
        public VariableTableInterface variableTableInterface { get; set; } = new VariableTableInterface();

        //虚拟节点仅有一个使能输出
        public PlcBool eno { get; set; }


        //虚节点有多个使能输入，只要其中一个使能输入是通的，那么使能输出就是通的

        public List<PlcBool> enList { get; set; } = new List<PlcBool>();



        /// <summary>
        /// 使能输出线，含有很多条
        /// </summary>
        public List<Connector<PlcBool>> enableLines = new List<Connector<PlcBool>>();

        /// <summary>
        /// 使能输入线，对应到使能输入列表
        /// </summary>
        public Dictionary<string ,Connector<PlcBool>> enLineDict { get; set; }   =   new();

        public VirtualNode()
        {
            //把eno添加到接口中
            variableTableInterface.AddVariable("out", StorageType.Output, new PlcBool());

            eno = variableTableInterface.GetVariableValue<PlcBool>("out");
        }

 

  


     /// <summary>
     /// 虚拟节点作为第一个元素连接其他图元节点
     /// </summary>
     /// <param name="node"></param>
     /// <param name="FromName"></param>
     /// <param name="ToName"></param>
     /// <exception cref="Exception"></exception>
        public void Connect(IGraphNode node, string FromName, string ToName)
        {
            if (FromName != "out") throw new Exception("发现连线中虚拟的点作为第一个，但是属性名并不是out");
            var test = new Connector<PlcBool>();
            test.From = eno;
            test.FromNode = this;
            test.To = (PlcBool)node.GetInterfaceVariableByName(ToName);
            test.ToNode = node;
            enableLines.Add(test);
        }

        public IPlcMember GetInterfaceVariableByName(string name)
        {
            // 使用正则表达式匹配 "in" 或 "out" 开头，后跟一个或多个数字
            Match match = Regex.Match(name, @"^(?:out|in\d+)$", RegexOptions.IgnoreCase);
            if (match.Success) {
                if (variableTableInterface.ContainsKey(name))
                {
                   return variableTableInterface.GetVariableValue<IPlcMember>(name);
                }
                else
                {
                    var input = new PlcBool();
                    variableTableInterface.AddVariable(name, StorageType.Input, input);
                    //这里是找不到才会新加一个
                    enList.Add(input);
                    return input;
                }

            }
            else 
            {
                if(name == "in")//传入的属性只有in，说名是在新建了
                {
                    string str  = "in"+(enList.Count+1);
                    PlcBool plcBool = new PlcBool();
                    variableTableInterface.AddVariable(str, StorageType.Input, plcBool);
                    enList.Add(plcBool);
                    return plcBool;
                }
                throw new Exception("虚拟节点中字符串属性不符合规范");
            }
          
        }
    }
}
